package com.hghivln.blog.shiro;

import com.alibaba.fastjson.JSONObject;
import com.hghivln.blog.common.lang.Result;
import com.hghivln.blog.common.lang.ResultEnum;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginFilter extends FormAuthenticationFilter {


    @Override
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
        // 登录成功之后 设置session时间为1天 单位为毫秒
        SecurityUtils.getSubject().getSession().setTimeout(-1000L);
        return super.onLoginSuccess(token, subject, request, response);
    }

    /**
     * 当用户访问未登录资源时，会走的方法
     * 返回true代表已登录，不用处理
     * 返回false代表未登录。提示前端
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        response.getWriter().write(JSONObject.toJSON(new Result<>(ResultEnum.NOT_LOGIN)).toString());
        return false;
    }

    /**
     * 对跨域提供支持
     * 拦截器的前置拦截，因为我们是前后端分析项目，项目中除了需要跨域全局配置之外，我们再拦截器中也需要提供跨域支持。
     * 这样，拦截器才不会在进入Controller之前就被限制了。
     * 跨域请求有一个前置请求,method类型OPTIONS。该请求会被shiro拦截，故而应该统统放行。
     */
    @Override
    public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
        HttpServletResponse httpServletResponse = WebUtils.toHttp(response);

        //无条件放行OPTIONS
        if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
            setHeader(httpServletRequest,httpServletResponse);
            return true;
        }
        return super.onPreHandle(request, response, mappedValue);
    }

    /**
     * 为response设置header，实现跨域
     */
    private void setHeader(HttpServletRequest request,HttpServletResponse response) {
        //  跨域的header设置
        //  该字段表明可供哪个源跨域
        response.setHeader("Access-control-Allow-Origin",request.getHeader("*"));
        //  该字段表明服务器支持的所有跨域请求的方法
        response.setHeader("Access-Control-Allow-Methods","GET,POST,OPTIONS,PUT,DELETE");
        //  实际请求将携带的自定义请求首部字段
        response.setHeader("Access-Control-Allow-Headers",request.getHeader("Access-control-Allow-Origin"));
        //防止乱码，适用于传输JSON数据
        response.setHeader("Content-Type", "application/json;charset=UTF-8");
        response.setStatus(ResultEnum.SUCCESS.getCode());
    }
}
